import socket
import struct
import json
import threading
import time
from python脚本.pyScripts import PackData_pb2, PackHeader_pb2


def create_message(header: PackHeader_pb2.Header, body: PackData_pb2.Body):
    # 序列化 Header 和 Body
    header_bytes = header.SerializeToString()
    body_bytes = body.SerializeToString()

    # 包边界和版本
    packet_boundary = 0xABCD
    version = 1

    # 包头长度和包体长度
    packet_header_length = len(header_bytes)
    packet_body_length = len(body_bytes)

    # 按照协议拼接二进制数据
    message = struct.pack(
        ">I I I I",  # 四个参数：包边界, 版本, 包头长度, 包体长度，“>”代表是按照大端排序
        packet_boundary,
        version,
        packet_header_length,
        packet_body_length,
    ) + header_bytes + body_bytes

    return message

def decode_response(response: bytes):
    try:
        # 按照协议解码
        if len(response) < 16:
            print("Invalid response format: insufficient length")
            return

        # 提取包边界、版本、长度信息
        packet_boundary, version, header_length, body_length = struct.unpack(
            ">I I I I", response[:16]
        )

        # 验证包边界
        if packet_boundary != 0xABCD:
            print("Invalid packet boundary in response")
            return

        # 提取包头和包体
        header_bytes = response[16:16 + header_length]
        body_bytes = response[16 + header_length:16 + header_length + body_length]

        # 反序列化 Protobuf 消息
        header = PackHeader_pb2.Header()
        header.ParseFromString(header_bytes)

        body = PackData_pb2.Body()
        body.ParseFromString(body_bytes)

        print("Decoded Response:")
        print(f"Header: {header}")
        print(f"Body: {body}")

    except Exception as e:
        print(f"Error decoding response: {e}")

def receive_messages(client_socket):
    """单独线程用于接收服务器消息"""
    try:
        while True:
            response = client_socket.recv(1024)
            if not response:
                print("Server closed connection.")
                break
            decode_response(response)
    except Exception as e:
        print(f"Error in receiving messages: {e}")

def send_heartbeat(client_socket, sender_id):
    """定时发送心跳包"""
    try:
        while True:
            time.sleep(10)  # 每10秒发送一次心跳

            header = PackHeader_pb2.Header(
                appId=1,
                uid=sender_id,
                token="valid-token",
                bizId=1,
                messageType=1,  # 心跳类型
                compression=0,
                encryption=0,
            )

            body = PackData_pb2.Body(
                data=json.dumps({"message": "heartbeat"})
            )

            heartbeat_message = create_message(header, body)
            client_socket.sendall(heartbeat_message)
            print("Heartbeat sent to server.")

    except Exception as e:
        print(f"Error in sending heartbeat: {e}")

def start_persistent_connection(host: str, port: int):
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as client_socket:
        client_socket.connect((host, port))
        print(f"Connected to server {host}:{port}")

        try:
            # 启动接收线程
            threading.Thread(target=receive_messages, args=(client_socket,), daemon=True).start()

            # 默认触发登录
            sender_id = int(input("请输入发送者ID: "))
            header = PackHeader_pb2.Header(
                appId=1,
                uid=sender_id,
                token="valid-token",
                bizId=1,
                messageType=0,  # 登录类型
                compression=0,
                encryption=0,
            )

            body = PackData_pb2.Body(
                data=json.dumps({"message": "login request"})
            )

            login_message = create_message(header, body)
            client_socket.sendall(login_message)
            print("Login request sent to server.")

            # 启动心跳线程
            threading.Thread(target=send_heartbeat, args=(client_socket, sender_id), daemon=True).start()

            # 消息发送逻辑
            while True:
                command = input("输入 'send' 发送消息，输入 'exit' 退出: ").strip().lower()
                if command == 'send':
                    receiver_id = input("接收方ID: ")
                    text = input("消息内容: ")

                    json_data = {
                        "sender_id": sender_id,
                        "receiver_id": receiver_id,
                        "timestamp": "1672531199000",
                        "message_id": "9999",
                        "message_type": 3,  # 消息推送
                        "context": text,
                    }

                    # 创建消息 Header 和 Body
                    header = PackHeader_pb2.Header(
                        appId=1,
                        uid=sender_id,
                        token="valid-token",
                        bizId=1,
                        messageType=3,  # 消息IM推送类型
                        compression=0,
                        encryption=0,
                    )

                    body = PackData_pb2.Body(
                        data=json.dumps(json_data)  # JSON 格式的数据
                    )

                    # 生成协议消息
                    message = create_message(header, body)

                    # 发送消息
                    client_socket.sendall(message)
                    print("Message sent to server.")

                elif command == 'exit':
                    print("Closing connection.")
                    break

        except KeyboardInterrupt:
            print("Connection closed by client.")

# 启动长连接客户端
start_persistent_connection(host="127.0.0.1", port=7894)
